Customizing the Property Grid

The appearance and user interaction of the property grid can be customized using the Editors property. The Editors property allows you to select editors other than the default editors, to customize the appearance of editors using WPF styling and templating, and to create your own editor user interfaces.

Selecting Nondefault Editors

Consider a Person with a numeric Age property. By default, the age is displayed in a text box and the user can edit its value by typing into the text box. Suppose however we would like users to be able to use a slider to edit the age. The property grid includes a slider editor. We can specify the use of this editor for the Age property as follows:

CopyUsing the slider editor
<ms:PropertyGrid.Editors>
      <ms:PropertyEditor PropertyName='Age' DeclaringType='{x:Type t:Person}' EditorTemplate='{StaticResource {x:Static ms:PropertyGrid.SliderEditorKey}}'/>
    </ms:PropertyGrid.Editors>

See Built-In Editors for a list of available editors.

Customizing the Appearance or Behavior of an Existing Editor

The previous example displays a slider control, but the default slider range of 0 to 10 isn’t really appropriate to an Age property. We’d like to change this to, say, 0 to 150, and to increase the LargeChange amount accordingly. This can be done as follows:

CopyUsing the slider editor with bounds
<ms:PropertyEditor PropertyName='Age' DeclaringType='{x:Type t:Person}' EditorTemplate='{StaticResource {x:Static ms:PropertyGrid.SliderEditorKey}}'>
            <ms:PropertyEditor.Style>
              <Style>
                <Setter Property='Slider.Minimum' Value='0'/>
                <Setter Property='Slider.Maximum' Value='150'/>
                <Setter Property='Slider.LargeChange' Value='25'/>
              </Style>
            </ms:PropertyEditor.Style>
          </ms:PropertyEditor>

The PropertyEditor.Style property can be used for more extensive customizations, including retemplating the control to give it a completely custom visual appearance. See the Editors sample for an example of retemplating the check box editor.

Use the source code for the built-in styles as a starting point. See the Source folder in your installation directory.
 

Creating Your Own Editor User Interfaces

Sometimes it is not possible to adapt a built-in editor to specialised data or user interface requirements. For example, a PhoneNumber type with separate CountryCode, RegionCode and Number properties is not going to be editable using any of the built-in controls because the data model does not match up. A HatSize property could be edited using the built-in editors, but if you want to display it as a resizeable picture of a hat, restyling the built-in editors may not be feasible.

In these cases you can create your own editor user interfaces. To do this you must create a data template which the property grid can bind to an appropriate property value. For example, a template for editing phone numbers might look like this:

CopyPhone number editor
<DataTemplate x:Key='PhoneNumberEditor'>
      <StackPanel Margin='{Binding DefaultMargin, RelativeSource={RelativeSource AncestorType={x:Type ms:PropertyGrid}}}' KeyboardNavigation.TabNavigation='Local' Background='{DynamicResource {x:Static SystemColors.WindowBrushKey}}' Height='40' Orientation='Horizontal' TextBlock.Foreground='{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}'>
        <TextBlock>+</TextBlock>
        <ms:TextBox BorderThickness='0' Text='{Binding Path=CountryCode, UpdateSourceTrigger=PropertyChanged}' MinWidth='10'/>
        <TextBlock> (</TextBlock>
        <ms:TextBox BorderThickness='0' Text='{Binding Path=RegionCode, UpdateSourceTrigger=PropertyChanged}' MinWidth='10'/>
        <TextBlock>)</TextBlock>
        <ms:TextBox BorderThickness='0' Text='{Binding Path=Number, UpdateSourceTrigger=PropertyChanged}' MinWidth='10'/>
      </StackPanel>
    </DataTemplate>

This can then be invoked as follows:

CopyPhone number editor invocation
<ms:TypeEditor EditedType='{x:Type t:PhoneNumber}' EditorTemplate='{StaticResource PhoneNumberEditor}'/>

Note that the template will be bound to an object of type PhoneNumber, and therefore the binding paths specified in the template are simply the property names of the PhoneNumber type. But what if we need to edit a primitive value? For example, the HatSize property is of type double: there is no property on the Double type that our template could bind to.

The answer is that a property editor defines a special Value property, which its data template must bind to. Thus, our hat size editor might look something like this:

CopyHat size editor
<DataTemplate x:Key='HatSizeEditor'>
      <!-- display the little-known Ruritanian ultra-flat cap for ease of drawing -->
      <Ellipse Width='{Binding Path=Value}' Height='{Binding Path=Value}'/>
    </DataTemplate>

and be invoked as follows:

CopyHat size editor invocation
<ms:PropertyEditor PropertyName='HatSize' DeclaringType='{x:Type t:Person}' EditorTemplate='{StaticResource HatSizeEditor}'/>

Sometimes it is useful for users to expand a node in order to examine or edit individual properties, even though you have supplied a custom editor for the value. To allow this, set AllowExpand=”True” when declaring the editor.